package com.tsing.wms.config;

import cn.hutool.core.util.StrUtil;
import cn.hutool.jwt.JWT;
import com.tsing.wms.annotation.PassToken;
import com.tsing.wms.constant.AuthConsts;
import com.tsing.wms.dto.UserDTO;
import com.tsing.wms.exception.CommonException;
import com.tsing.wms.exception.ServerException;
import com.tsing.wms.util.GetLoginUserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;

/**
 * @author TheTsing
 */
public class JwtInterceptor implements HandlerInterceptor {

    @Value("${frame.auth.support:false}")
    private String authSupport;

    @Autowired
    private RedisManager redisManager;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (!"true".equals(authSupport)) {
            return true;
        }
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        if (method.isAnnotationPresent(PassToken.class)) {
            return true;
        }
        String token = request.getHeader(AuthConsts.AUTHENTICATION_HEAD);
        UserDTO userDTO = GetLoginUserUtil.getLoginUserInfo(token, redisManager);
        //登录失败次数验证
        String count = redisManager.getString(AuthConsts.REDIS_LOGIN_COUNT_PREFIX + userDTO.getId());
        if (StrUtil.isNotBlank(count) && Integer.parseInt(count) > AuthConsts.LIMIT_LOGIN_ACCOUNT) {
            throw new ServerException(CommonException.Proxy.ACCOUNT_LIMIT_LOGIN);
        }
        boolean verify;
        try {
            verify = JWT.of(token).setKey(userDTO.getId().getBytes(StandardCharsets.UTF_8)).verify();
        } catch (Exception e) {
            throw new ServerException(CommonException.Proxy.TOKEN_VERIFY_ERROR);
        }
        if (!verify) {
            throw new ServerException(CommonException.Proxy.TOKEN_VERIFY_ERROR);
        }
        redisManager.resetStringExpire(userDTO.getToken(), userDTO.getExpire());
        redisManager.resetStringExpire(AuthConsts.REDIS_TOKEN_PREFIX + userDTO.getId(), userDTO.getExpire());
        return true;
    }

}
